"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 服务端工具
Case Name   : gs_om -t cert分发证书不执行指定日志路径成功（单机）
Create At   : 2022/06/10
@zou_jialiang0501129488
Description :
    1.一主两备减容至单机数据库
    2.拷贝normal.zip至本机后不指定日志路径执行证书分发操作
    gs_om -t cert --cert-file normal.zip
    3.执行扩容恢复环境，清理文件
Expect      :
    1.数据库减容成功
    2.证书分发成功
    3.环境恢复成功
History     :
    modified by @daiguatutu at 2022-10-3:拷贝文件的执行用户修改为数据库用户,避免权限问题执行失败
    modified by @daiguatutu at 2022-11-22:代码变更，优化断言
    modified by @daiguatutu at 2023-02-10:修改创建互信的执行路径
"""
import os
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.Common import Common
from testcase.utils.Common import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger

COMMONSH = CommonSH("PrimaryDbUser")
Constant = Constant()


@unittest.skipIf(3 != COMMONSH.get_node_num(), '非1+2环境不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.common = Common()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.primary_root_node = Node('PrimaryRoot')
        self.primary_node = Node('PrimaryDbUser')
        self.standby1_root_node = Node('Standby1Root')
        self.standby1_node = Node('Standby1DbUser')
        self.standby2_node = Node('Standby2DbUser')
        self.com_root = CommonSH("PrimaryRoot")
        self.s_com1 = CommonSH("Standby1DbUser")
        self.s_com2 = CommonSH("Standby2DbUser")
        self.u_name = self.primary_node.ssh_user
        self.log_path = os.path.join(os.path.dirname(macro.DB_INSTANCE_PATH),
                                     'cert.log')
        self.cert_path = os.path.join(os.path.dirname(macro.DB_INSTANCE_PATH),
                                      'cert_file')
        self.cert_file = os.path.join(self.cert_path, 'normal.zip')
        self.log.info("查询synchronous_standby_names默认值")
        result = COMMONSH.execut_db_sql("show synchronous_standby_names")
        self.assertTrue(2 <= len(result))
        self.log.info(f"primary synchronous_standby_names is {result}")
        self.synchronous_standby_names_p = result.strip().splitlines()[-2]
        result = self.s_com1.execut_db_sql("show synchronous_standby_names")
        self.assertTrue(2 <= len(result))
        self.log.info(f"s1 synchronous_standby_names is {result}")
        self.synchronous_standby_names_s1 = result.strip().splitlines()[-2]
        result = self.s_com2.execut_db_sql("show synchronous_standby_names")
        self.assertTrue(2 <= len(result))
        self.log.info(f"s2 synchronous_standby_names is {result}")
        self.synchronous_standby_names_s2 = result.strip().splitlines()[-2]

        self.host_tuple = (self.primary_node.ssh_host,
                           self.standby1_node.ssh_host,
                           self.standby2_node.ssh_host)
        self.params = {'-f': 'test_hosts'}

    def test_gs_om(self):
        text = '----step1:执行gs_dropnode进行备机减容 expect:成功'
        self.log.info(text)
        global log_path
        log_path = os.path.join(self.log_path, 'cert*.log')
        drop_cmd = f'gs_dropnode -U {self.u_name} -G {self.u_name} ' \
                   f'-h {self.standby1_node.ssh_host},' \
                   f'{self.standby2_node.ssh_host}'
        self.log.info(drop_cmd)
        global shell_path
        shell_path = os.path.join(os.path.dirname(macro.DB_INSTANCE_PATH),
                                  'dropnode.sh')
        shell_cmd = f'touch {shell_path};echo -e {drop_cmd} > {shell_path};' \
                    f'chmod 755 {shell_path};cat {shell_path}'
        self.log.info(shell_cmd)
        shell_res = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(shell_res)
        drop_cmd = f'''source {macro.DB_ENV_PATH}
                       expect <<EOF
                       set timeout 300
                       spawn {shell_path}
                       expect {{{{
                       "*(yes/no)?" {{{{ send "yes\n"; \
                       exp_continue }}}}
                       eof }}}}\n''' + "EOF"
        self.log.info(drop_cmd)
        drop_res = self.primary_node.sh(drop_cmd).result()
        self.log.info(drop_res)
        self.assertIn('Success to drop the target nodes', drop_res,
                      text + '减容失败')

        self.log.info('检查数据库是否减容')
        status_cmd = f'source {macro.DB_ENV_PATH};' \
                     f'gs_om -t status --detail;'
        self.log.info(status_cmd)
        check_res = self.primary_node.sh(status_cmd).result()
        self.log.info(check_res)
        self.assertNotIn(self.standby1_node.ssh_host and
                         self.standby2_node.ssh_host,
                         check_res, '数据库状态检查失败')

        text = '----step2:传输文件并执行cert操作 expect:成功----'
        self.log.info(text)
        self.common.scp_file(self.primary_node, 'normal.zip',
                             self.cert_path)
        cert_cmd = f'source {macro.DB_ENV_PATH};' \
                   f'gs_om -t cert --cert-file {self.cert_file}'
        self.log.info(cert_cmd)
        cert_res = self.primary_node.sh(cert_cmd).result()
        self.log.info(cert_res)
        check_msg = f'Successfully distributed cert files on all nodes'
        self.assertIn(check_msg, cert_res, '证书分发失败')

    def tearDown(self):
        text = "----step3：恢复环境 expect:成功----"
        self.log.info(text)
        rollback_cmd = f'source {macro.DB_ENV_PATH};' \
                       f'gs_om -t cert -l {self.log_path} --rollback'
        self.log.info(rollback_cmd)
        check_cmd = f'cd {os.path.dirname(self.log_path)};' \
                    f'ls {os.path.dirname(self.log_path)} | ' \
                    f'grep cert*.log | xargs cat'
        rollback_res = self.primary_node.sh(rollback_cmd).result()
        self.log.info(rollback_res)
        log_check = self.primary_root_node.sh(check_cmd).result()
        self.log.info(log_check)

        self.log.info('-----创建root互信,扩容备1-----')
        script_path = os.path.join(os.path.dirname(macro.DB_INSTANCE_PATH),
                                   'tool', 'script')
        self.com_root.exec_gs_sshexkey(script_path,
                                       *self.host_tuple,
                                       **self.params)
        result1 = self.com_root.exec_expension(f"{self.primary_node.ssh_user}",
                                               f"{self.primary_node.ssh_user}",
                                               f"{self.standby1_node.ssh_host}",
                                               f"{macro.DB_XML_PATH}")
        self.log.info(result1)

        self.log.info('-----创建root互信，扩容备2-----')
        self.com_root.exec_gs_sshexkey(script_path,
                                       *self.host_tuple,
                                       **self.params)
        result2 = self.com_root.exec_expension(f"{self.primary_node.ssh_user}",
                                               f"{self.primary_node.ssh_user}",
                                               f"{self.standby2_node.ssh_host}",
                                               f"{macro.DB_XML_PATH}")
        self.log.info(result2)

        self.log.info('-----删除创建文件-----')
        del_cmd = f"rm -rf {self.cert_path};" \
                  f"rm -rf {shell_path};" \
                  f"rm -rf {log_path}"
        self.log.info(del_cmd)
        del_res = self.primary_root_node.sh(del_cmd).result()
        self.log.info(del_res)

        self.log.info("恢复各节点synchronous_standby_names")
        COMMONSH.execute_gsguc("reload",
                               Constant.GSGUC_SUCCESS_MSG,
                               f"synchronous_standby_names="
                               f"'{self.synchronous_standby_names_p}'",
                               single=True)
        self.s_com1.execute_gsguc("reload",
                                  Constant.GSGUC_SUCCESS_MSG,
                                  f"synchronous_standby_names="
                                  f"'{self.synchronous_standby_names_s1}'",
                                  single=True)
        self.s_com2.execute_gsguc("reload",
                                  Constant.GSGUC_SUCCESS_MSG,
                                  f"synchronous_standby_names="
                                  f"'{self.synchronous_standby_names_s2}'",
                                  single=True)
        self.log.info(f'----{os.path.basename(__file__)} finish----')
        self.assertEqual(1, rollback_res.count('Successfully rollback'),
                         '证书回滚失败')
        self.assertEqual('', del_res, '文件删除失败')
        self.assertTrue(result1)
        self.assertTrue(result2)
